package messaging

import (
	"fmt"
	"net"
	"sync"
	"time"

	"github.com/zeromicro/go-zero/core/logx"
)

// ConnectionManager 连接管理器
type ConnectionManager struct {
	connections map[string]*DeviceConnection
	mutex       sync.RWMutex
	logger      logx.Logger
}

// DeviceConnection 设备连接信息
type DeviceConnection struct {
	DeviceID   string
	Protocol   string // tcp, udp
	RemoteAddr string // IP:Port
	Conn       net.Conn
	LastActive time.Time
	IsActive   bool
}

// NewConnectionManager 创建新的连接管理器
func NewConnectionManager() *ConnectionManager {
	cm := &ConnectionManager{
		connections: make(map[string]*DeviceConnection),
		logger:      logx.WithCallerSkip(1),
	}

	// 启动连接清理协程
	go cm.connectionCleanupWorker()

	return cm
}

// GetOrCreateConnection 获取或创建设备连接
func (cm *ConnectionManager) GetOrCreateConnection(deviceID, protocol, remoteAddr string) (*DeviceConnection, error) {
	cm.mutex.Lock()
	defer cm.mutex.Unlock()

	// 检查是否已存在连接
	if conn, exists := cm.connections[deviceID]; exists && conn.IsActive {
		conn.LastActive = time.Now()
		return conn, nil
	}

	// 创建新连接
	conn, err := cm.createConnection(deviceID, protocol, remoteAddr)
	if err != nil {
		return nil, err
	}

	cm.connections[deviceID] = conn
	cm.logger.Infof("创建新连接: 设备=%s, 协议=%s, 地址=%s", deviceID, protocol, remoteAddr)

	return conn, nil
}

// createConnection 创建新连接
func (cm *ConnectionManager) createConnection(deviceID, protocol, remoteAddr string) (*DeviceConnection, error) {
	var conn net.Conn
	var err error

	switch protocol {
	case "tcp":
		conn, err = net.DialTimeout("tcp", remoteAddr, 5*time.Second)
	case "udp":
		udpAddr, uErr := net.ResolveUDPAddr("udp", remoteAddr)
		if uErr != nil {
			return nil, fmt.Errorf("解析UDP地址失败: %v", uErr)
		}
		conn, err = net.DialUDP("udp", nil, udpAddr)
	default:
		return nil, fmt.Errorf("不支持的协议: %s", protocol)
	}

	if err != nil {
		return nil, fmt.Errorf("创建连接失败: %v", err)
	}

	deviceConn := &DeviceConnection{
		DeviceID:   deviceID,
		Protocol:   protocol,
		RemoteAddr: remoteAddr,
		Conn:       conn,
		LastActive: time.Now(),
		IsActive:   true,
	}

	return deviceConn, nil
}

// SendMessage 通过连接发送消息
func (cm *ConnectionManager) SendMessage(deviceID string, message []byte) error {
	cm.mutex.RLock()
	conn, exists := cm.connections[deviceID]
	cm.mutex.RUnlock()

	if !exists || !conn.IsActive {
		return fmt.Errorf("设备连接不存在或已断开: %s", deviceID)
	}

	// 设置写超时
	conn.Conn.SetWriteDeadline(time.Now().Add(5 * time.Second))

	// 发送消息
	_, err := conn.Conn.Write(message)
	if err != nil {
		// 标记连接为无效
		cm.markConnectionInactive(deviceID)
		return fmt.Errorf("发送消息失败: %v", err)
	}

	// 更新最后活动时间
	conn.LastActive = time.Now()

	return nil
}

// markConnectionInactive 标记连接为无效
func (cm *ConnectionManager) markConnectionInactive(deviceID string) {
	cm.mutex.Lock()
	defer cm.mutex.Unlock()

	if conn, exists := cm.connections[deviceID]; exists {
		conn.IsActive = false
		if conn.Conn != nil {
			conn.Conn.Close()
		}
		cm.logger.Errorf("连接标记为无效: 设备=%s", deviceID)
	}
}

// CloseConnection 关闭设备连接
func (cm *ConnectionManager) CloseConnection(deviceID string) error {
	cm.mutex.Lock()
	defer cm.mutex.Unlock()

	if conn, exists := cm.connections[deviceID]; exists {
		if conn.Conn != nil {
			err := conn.Conn.Close()
			if err != nil {
				cm.logger.Errorf("关闭连接失败: 设备=%s, 错误=%v", deviceID, err)
			}
		}
		delete(cm.connections, deviceID)
		cm.logger.Infof("连接已关闭: 设备=%s", deviceID)
	}

	return nil
}

// CloseAllConnections 关闭所有连接
func (cm *ConnectionManager) CloseAllConnections() {
	cm.mutex.Lock()
	defer cm.mutex.Unlock()

	for deviceID, conn := range cm.connections {
		if conn.Conn != nil {
			conn.Conn.Close()
		}
		delete(cm.connections, deviceID)
	}

	cm.logger.Info("所有连接已关闭")
}

// connectionCleanupWorker 连接清理工作协程
func (cm *ConnectionManager) connectionCleanupWorker() {
	ticker := time.NewTicker(1 * time.Minute)
	defer ticker.Stop()

	for {
		for range ticker.C {
			cm.cleanupInactiveConnections()
		}
	}
}

// cleanupInactiveConnections 清理不活跃的连接
func (cm *ConnectionManager) cleanupInactiveConnections() {
	cm.mutex.Lock()
	defer cm.mutex.Unlock()

	now := time.Now()
	for deviceID, conn := range cm.connections {
		// 清理超过10分钟不活跃的连接
		if now.Sub(conn.LastActive) > 10*time.Minute {
			if conn.Conn != nil {
				conn.Conn.Close()
			}
			delete(cm.connections, deviceID)
			cm.logger.Infof("清理不活跃连接: 设备=%s", deviceID)
		}
	}
}

// GetConnectionStats 获取连接统计信息
func (cm *ConnectionManager) GetConnectionStats() map[string]interface{} {
	cm.mutex.RLock()
	defer cm.mutex.RUnlock()

	stats := make(map[string]interface{})
	stats["total_connections"] = len(cm.connections)

	activeCount := 0
	for _, conn := range cm.connections {
		if conn.IsActive {
			activeCount++
		}
	}
	stats["active_connections"] = activeCount
	stats["inactive_connections"] = len(cm.connections) - activeCount

	return stats
}
